package cgl.narada.transport.rtp;
/**
 * Software License, Version 1.0
 *
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 *
 *Redistribution and use in source and binary forms, with or without
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For
 * further information contact the Community Grids Lab at
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and
 * wherever such third-party acknowledgments normally appear.
 *
 *4) The name Indiana University or Community Grids Lab or GlobalMMCS,
 * shall not be used to endorse or promote products derived from this software
 * without prior written permission from Indiana University.  For written
 * permission, please contact the Advanced Research and Technology Institute
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called GlobalMMCS,
 * nor may Indiana University or Community Grids Lab or GlobalMMCS appear
 * in their name, without prior written permission of ARTI.
 *
 * Indiana University provides no reassurances that the source code provided
 * does not infringe the patent or any other intellectual property rights of
 * any other entity.  Indiana University disclaims any liability to any
 * recipient for claims brought by any other entity based on infringement of
 * intellectual property rights or otherwise.
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS.
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS",
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION
 *GENERATED USING SOFTWARE.
 */


/**
 * this class describes a session on NaradaBrokering
 * It has the base topic number and the list of used topic numbers
 * sessionID is the base topic number
 * Every session can have sessionSize/2 rtp streams
 *
 * @author Ahmet Uyar
 * @version 1.0
 */

import java.util.ArrayList;

public class SessionTopicManager {

   private int sessionID; //this is the base topic number for this Session
   private int currentMax; // this shows the current max topic number used in this session
   private int maxTopicNumber; // this shows the maximum topic number which can be used in this session
                               // it is sessionID + sessionSize - 2
   private int sessionSize;
   private ArrayList topicList;

   /**
    * If the number of streams is not given, then use 1000 as the default
    */
   public SessionTopicManager(int baseTopicNumber){
      this(baseTopicNumber, 1000);
   }

   /**
    * construct an object of this class with the given parameters
    */
   public SessionTopicManager(int baseTopicNumber, int sessionSize){
      sessionID = baseTopicNumber;
      currentMax = baseTopicNumber;
      this.sessionSize = sessionSize;
      maxTopicNumber = baseTopicNumber + sessionSize - 2;
      topicList = new ArrayList();
   }

   /**
    * return the sessionID which is the base topic number
    */
   public int getSessionID(){
      return sessionID;
   }

   /**
    * return maxTopicNumber
    */
   public int getSessionSize(){
      return sessionSize;
   }

   /**
    * return maxTopicNumber
    */
   public int getMaxTopicNumber(){
      return maxTopicNumber;
   }

   /**
    * add a topic number to the session.
    * assigns the topic numbers in increasing order, until it reaches the maximum
    * then it reassigns the deleted topic numbers from the bottom.
    *
    * if the topicList is full, return -1
    */
   public int addTopic() throws Exception{

      //if no topic is added yet, add the base topic number
      if(topicList.size() == 0){
         topicList.add(new Integer(sessionID));
         return sessionID;
      }

      // if currentMax is less than maxTopicNumber
      // assign the currentMax + 2 as the new topic number
      if(currentMax < maxTopicNumber){
         currentMax = currentMax + 2;
         topicList.add( new Integer(currentMax));
         return currentMax;
      }

      // find a deleted session and add it
      Integer deletedTopicNumber = getDeletedTopicNumber();
      if(deletedTopicNumber != null){
         topicList.add( deletedTopicNumber );
         return deletedTopicNumber.intValue();
      }

      // the topicList is full. return -1
      throw new Exception("SessionTopicManager is full. Try deleting some topics first.");
   }

   /**
    * deletes the given topic number
    * return true if successful, false otherwise
    */
   public boolean removeTopic(int t){

      Integer topic = new Integer(t);
      if(topicList.contains(topic)){
         topicList.remove(topic);
         return true;
      }

      return false;
   }

   /**
    * deletes the given topic number
    * return true if successful, false otherwise
    */
   public void removeAll(){

      topicList.clear();
   }

   /**
    * this method returns the first deleted integer from the topicList if there is any
    * otherwise returns null.
    *
    * we assume that there is at least one element in the topicList
    */
   private Integer getDeletedTopicNumber(){

      //see whether any element is deleted
      for (int i = sessionID; i < maxTopicNumber + 2; i+=2) {

         Integer newInt = new Integer(i);
         if( !topicList.contains( newInt )){
            return newInt;
         }

      }

      return null;
   }

   /**
    * return the minimum of the elements in topicList
    * we assume that there is at least one element in the list
    *
    * currently it is not being used
    */
   private Integer getMin(){

      Integer min = (Integer)topicList.get(0);
      Integer current;

      for (int i = 0; i < topicList.size(); i++) {
         current = (Integer)topicList.get(i);
         if(min.intValue() > current.intValue()){
            min = current;
         }
      }

      return min;
   }

   /**
    * return the maximum of the elements in topicList
    * we assume that there is at least one element in the list
    *
    * currently it is not being used
    */
   private Integer getMax(){

      Integer max = (Integer)topicList.get(0);
      Integer current;

      for (int i = 0; i < topicList.size(); i++) {
         current = (Integer)topicList.get(i);
         if(max.intValue() < current.intValue()){
            max = current;
         }
      }

      return max;
   }

   /**
    * if baseTopicNumbers are equal, return true
    * otherwise false
    */
   public boolean equals(Object obj) {

      //check whether this Object is a SessionDescription object
      if( obj instanceof SessionTopicManager){
         SessionTopicManager theOther = (SessionTopicManager)obj;
         if(sessionID == theOther.getSessionID()){
            return true;
         }
      }

      return false;
   }

   /**
    * toString method implementation
    */
   public String toString(){
      return Integer.toString(sessionID);
   }

   /**
    * prints all integers in topic list
    */
   private void print(){
      System.out.println(topicList);
   }

   public static void main(String[] args) throws Exception{

      SessionTopicManager sd = new SessionTopicManager(1000, 100);


      for (int i = 0; i < 100; i++) {

         if( sd.addTopic() == -1){
            System.out.println(" can not add.");
         }

         if(i%10 == 0){
            System.out.println("added "+i+"th element");
         }
      }

      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      sd.print();

      System.out.println("topic deleted [1000]: "+sd.removeTopic( 1000 ));
      System.out.println("topic deleted [1008]: "+sd.removeTopic( 1008 ));
      System.out.println("topic deleted [1010]: "+sd.removeTopic( 1010 ));
      System.out.println("topic deleted [1018]: "+sd.removeTopic( 1018 ));
      System.out.println("topic deleted [1998]: "+sd.removeTopic( 1998 ));
      sd.print();

      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      System.out.println("topic added: "+sd.addTopic());
      sd.print();

   }

}
